package com.lwc.backendsinglestructure.service.impl;

import cn.hutool.core.net.URLEncodeUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.lwc.backendsinglestructure.domain.vo.wx.ReceiveMessage;
import com.lwc.backendsinglestructure.domain.vo.wx.WeixinQrCode;
import com.lwc.backendsinglestructure.service.WxService;
import com.lwc.backendsinglestructure.utils.WeixinMsgUtil;
import com.lwc.backendsinglestructure.utils.cache.CacheUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Arrays;

@Slf4j
@Service
public class WxServiceImpl implements WxService {

    @Autowired
    private CacheUtil cacheUtil;
    @Value("${weixin.token}")
    private String token;

    @Value("${weixin.appid}")
    public String appId;

    @Value("${weixin.appsecret}")
    public String appSecret;

    private static String QR_CODE_URL_PREFIX = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=";

    private static String ACCESS_TOKEN = null;
    private static LocalDateTime ACCESS_TOKEN_EXPIRE_TIME = null;
    /**
     * 二维码 Ticket 过期时间
     */
    private static int QR_CODE_TICKET_TIMEOUT = 10 * 60;

    /**
     * 获取 access token
     *
     * @return
     */
    public synchronized String getAccessToken() {
        if (ACCESS_TOKEN != null && ACCESS_TOKEN_EXPIRE_TIME.isAfter(LocalDateTime.now())) {
            return ACCESS_TOKEN;
        }
        String api = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret="
                + appSecret;
        String result = HttpUtil.get(api);
        JSONObject jsonObject = JSONUtil.parseObj(result);
        ACCESS_TOKEN = jsonObject.getStr("access_token");
        ACCESS_TOKEN_EXPIRE_TIME = LocalDateTime.now().plusSeconds(jsonObject.getLong("expires_in") - 10);
        return ACCESS_TOKEN;
    }

    @Override
    public WeixinQrCode getQrCode() {
        // 1.首先调用微信服务器换取 AccessToken
        String accessToken = getAccessToken();
        // 2.再携带 AccessToken 获取 临时二维码
        String api = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + accessToken;
        // expire_seconds 二维码过期时间 秒为单位
        // action_name QR_STR_SCENE(临时字符串)
        // action_info ：二维码详细信息
        // scene 非必填
        String jsonBody = String.format("{\n"
                + "  \"expire_seconds\": %d,\n"
                + "  \"action_name\": \"QR_STR_SCENE\",\n"
                + "  \"action_info\": {\n"
                + "    \"scene\": {\n"
                + "      \"scene_str\": \"%s\"\n"
                + "    }\n"
                + "  }\n"
                + "}", QR_CODE_TICKET_TIMEOUT, RandomUtil.randomNumbers(5));
        String result = HttpUtil.post(api, jsonBody);
        WeixinQrCode weixinQrCode = JSONUtil.toBean(result, WeixinQrCode.class);
        // 通过ticket换取二维码 https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET  TICKET 要注意编码
//        weixinQrCode.setQrCodeUrl(QR_CODE_URL_PREFIX + URI.create(weixinQrCode.getTicket()).toASCIIString());
        String encodeTicket = URLEncodeUtil.encode(weixinQrCode.getTicket());
        weixinQrCode.setQrCodeUrl(QR_CODE_URL_PREFIX + encodeTicket);
        // 返回ticket给前端保存
        return weixinQrCode;
    }

    @Override
    public void checkSignature(String signature, String timestamp, String nonce) {
        String[] arr = new String[] {token, timestamp, nonce};
        Arrays.sort(arr);
        StringBuilder content = new StringBuilder();
        for (String str : arr) {
            content.append(str);
        }
        String tmpStr = DigestUtil.sha1Hex(content.toString());
        if (tmpStr.equals(signature)) {
            log.info("check success");
            return;
        }
        log.error("check fail");
        throw new RuntimeException("check fail");
    }

    @Override
    public String handleWeixinMsg(String requestBody) {

        ReceiveMessage receiveMessage = WeixinMsgUtil.msgToReceiveMessage(requestBody);
        // 扫码登录
        if (WeixinMsgUtil.isScanQrCode(receiveMessage)) {
            return handleScanLogin(receiveMessage);
        }
        // 关注
        if (WeixinMsgUtil.isEventAndSubscribe(receiveMessage)) {
            return receiveMessage.getReplyTextMsg("欢迎关注【JavaRel】公众号");
        }
        return receiveMessage.getReplyTextMsg("收到（自动回复）");
    }

    /**
     * 处理扫码登录
     *
     * @param receiveMessage
     * @return
     */
    private String handleScanLogin(ReceiveMessage receiveMessage) {
        String qrCodeTicket = WeixinMsgUtil.getQrCodeTicket(receiveMessage);
        if (cacheUtil.get(qrCodeTicket) == null) {
            // FromUserName ： 扫码者的openid唯一标识
            String openId = receiveMessage.getFromUserName();
            // ticket openid
            cacheUtil.set(qrCodeTicket, openId,600);
        }
        String redirectUrl = "http://1089e5a9.r36.cpolar.top/getUserInfo?ticket=" + qrCodeTicket;
        // 构造授权地址
        return receiveMessage.getReplyTextMsg("请点击链接授权： <a href=\"https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxec69271754a6bd7d&redirect_uri="+redirectUrl+"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect\">登录</a>");
    }




}
